package com.cal.utms.model.dealing;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import com.cal.utms.action.user_maintenance.LoginAction;
import com.cal.utms.dao.dealing.DealDao;
import com.cal.utms.dao.dealing.DealInstrumentMapDao;
import com.cal.utms.dao.dealing.InstrumentDao;
import com.cal.utms.dao.maintenance.DealTypeDao;
import com.cal.utms.dao.maintenance.IssuerDaoImpl;
import com.cal.utms.dao.maintenance.MasterDataDaoImpl;
import com.cal.utms.dao.maintenance.NewFundDao;
import com.cal.utms.dto.dealing.SaleDealDto;
import com.cal.utms.entity.Deal;
import com.cal.utms.entity.DealInstrumentMap;
import com.cal.utms.entity.Dealer;
import com.cal.utms.entity.DelevaryMethod;
import com.cal.utms.entity.Instrument;
import com.cal.utms.entity.InstrumentType;
import com.cal.utms.entity.SaledealMapping;
import com.cal.utms.entity.SettlementMethod;
import com.cal.utms.enumType.InterestRate;
import com.cal.utms.enumType.InterestType;
import com.cal.utms.util.Sequence;
import com.cal.utms.valuation.PurchaseCalculator;

public class SaleDealModel {

	public void mapPrevPurch(SaleDealDto saleDealDto, Deal purDeal) {
		NumberFormat nf = new DecimalFormat("###,##0.0000");
		NumberFormat ratenf = new DecimalFormat("###,##0.00");

		DealInstrumentMapDao dimDao = new DealInstrumentMapDao();
		Instrument instrument = dimDao.getByDeal(purDeal.getId()).getInstrument();

		if (purDeal.getMaturityValue() != null)
			saleDealDto.setPreDealVal(nf.format(purDeal.getMaturityValue().doubleValue()));

		// if (instrument != null && instrument.getInstrumentValue() != null) {
		// saleDealDto.setInsValue(nf.format(instrument.getInstrumentValue()));
		// } malsha

		if (purDeal.getMaturityValue() != null) {
			saleDealDto.setSellingAmount(nf.format(purDeal.getMaturityValue()));
		}
		saleDealDto.setPreIssuer(purDeal.getIssuer().getName());
		if (purDeal.getSecondaryMarket() == 0) {
			saleDealDto.setPreSecMarket(false);
		} else {
			saleDealDto.setPreSecMarket(true);
			saleDealDto.setPreSecSeller(purDeal.getSellerName());
		}
		if (instrument.getInstrumentType().getCouponAvailability() != 0) {
			if (instrument.getCouponRate() != null)
				saleDealDto.setPreCpnRate(ratenf.format(instrument.getCouponRate().doubleValue()) + "%");
			if (instrument.getInstrumentType().getCouponAvailability() == 1) {
				saleDealDto.setPreCpnDateFixed(true);
			}
		}
		if (instrument.getInstrumentType().getInterestRate() == InterestRate.F) {
			saleDealDto.setPreInterestFixed(true);
		} else {
			saleDealDto.setPreInterestFixed(false);
		}
		if (instrument.getInstrumentType().getInterestType() == InterestType.S) {
			saleDealDto.setPreInterestStraight(true);
		} else {
			saleDealDto.setPreInterestStraight(false);
		}

		if (instrument.getInstrumentType().getScripts() == 0) {
			saleDealDto.setPreScripts(false);
		} else {
			saleDealDto.setPreScripts(true);
		}
		if (instrument.getInstrumentType().getDenominals() == 0) {
			saleDealDto.setPreDenominals(false);
		} else {
			saleDealDto.setPreDenominals(true);
			if (instrument.getMinDenominal() != null)
				saleDealDto.setPreDenMinVal(String.valueOf(instrument.getMinDenominal().intValue()));
		}
		if (purDeal.getActualRate() != null)
			saleDealDto.setPreRate(ratenf.format(purDeal.getActualRate().doubleValue()) + "%");

		saleDealDto.setPreDealCode(purDeal.getDealCode());
	}

	public Deal createSaleDeal(SaleDealDto saleDealDto) {
		Deal deal = new Deal();
		deal.setCreatedDate(new Date());
		deal.setDealType(new DealTypeDao().getDealTypeByCode("SALE"));
		deal.setCreatedUser(LoginAction.getCurrentLogingUser().getUserName());
		deal.setStatus("Initial");

		Sequence seq = new Sequence();
		String dealCode = "SL" + seq.getNextValue("DealSequence");
		deal.setDealCode(dealCode);
		List<DealInstrumentMap> dimList = new ArrayList<DealInstrumentMap>();
		deal.setDealInstrumentMaps(dimList);
		return mapDtoToDeal(saleDealDto, deal);
	}

	public Deal updateSaleDeal(Deal deal, SaleDealDto saleDealDto) {
		deal.setModifiedDate(new Date());
		deal.setModifiedUser(LoginAction.getCurrentLogingUser().getUserName());
		return mapDtoToDeal(saleDealDto, deal);
	}

	public Deal confSaleDeal(SaleDealDto saleDealDto) {
		DealDao dealDao = new DealDao();
		Deal deal = dealDao.getByCode(saleDealDto.getDealCode());
		deal.setStatus("Confirmed");
		deal.setConfirmedUser(LoginAction.getCurrentLogingUser().getUserName());
		deal.setConfirmedDate(new Date());
		return mapDtoToDeal(saleDealDto, deal);
	}

	public Deal mapDtoToDeal(SaleDealDto saleDealDto, Deal deal) {
		NewFundDao nfd = new NewFundDao();
		DateFormat df = new SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH);
		NumberFormat format = NumberFormat.getInstance();
		Date result = null;
		Number number;
		IssuerDaoImpl issuerDao = new IssuerDaoImpl();

		deal.setFund(nfd.getById(saleDealDto.getFund()));
		deal.setIssuer(issuerDao.getById(saleDealDto.getBuyer()));
		try {
			result = df.parse(saleDealDto.getValueDate());
			deal.setValueDate(result);
		} catch (ParseException e) {
			System.out.println("Invalid Value:" + saleDealDto.getValueDate());
			e.printStackTrace();
			saleDealDto.setSuccess(false);
			saleDealDto.setStatus("Invalid Deal Value Date!");
			return deal;
		}
		try {
			number = format.parse(saleDealDto.getSellingValue());
			deal.setDealValue(new BigDecimal(number.doubleValue()));
		} catch (ParseException e) {
			System.out.println("Error in parsing Deal Value:" + saleDealDto.getSellingValue());
			saleDealDto.setSuccess(false);
			saleDealDto.setStatus("Invalid Deal Value!");
			return deal;
		}

		if (saleDealDto.getSellingAmount() != null) {
			try {
				number = format.parse(saleDealDto.getSellingAmount());
				deal.setMaturityValue(new BigDecimal(number.doubleValue()));
			} catch (ParseException e) {
				System.out.println("Error in parsing Maturity Value:" + saleDealDto.getSellingAmount());
				saleDealDto.setSuccess(false);
				saleDealDto.setStatus("Invalid Selling Amount!");
				return deal;
			}
		}

		MasterDataDaoImpl masterDataDaoImpl = new MasterDataDaoImpl();
		if (saleDealDto.getSettlementCode() != 0) {
			SettlementMethod method = masterDataDaoImpl.getSettlementById(saleDealDto.getSettlementCode());
			if (method != null) {
				System.out.println(method.getCode());
				deal.setSettlementMethod(method);
			} else {
				saleDealDto.setSuccess(false);
				saleDealDto.setStatus("Invalid Settlement Methode!");
				return deal;
			}
		}
		if (saleDealDto.getDelevarymethode() != 0) {
			DelevaryMethod delevaryMethod = masterDataDaoImpl.getDelevaryMethodById(saleDealDto.getDelevarymethode());
			if (delevaryMethod != null)
				deal.setDelevarymethode(delevaryMethod);
			else {
				saleDealDto.setSuccess(false);
				saleDealDto.setStatus("Invalid Delevary Methode!");
				return deal;
			}
		}

		if (saleDealDto.getDealerCode() != 0) {
			Dealer dealer = masterDataDaoImpl.getdealerByid(saleDealDto.getDealerCode());
			if (dealer != null)
				deal.setDealerCode(dealer);
			else {
				saleDealDto.setSuccess(false);
				saleDealDto.setStatus("Invalid Dealer!");
				return deal;
			}
		}

		System.out.println(saleDealDto.getSellingRate().replace("%", ""));
		deal.setActualRate(new BigDecimal(saleDealDto.getSellingRate().replace("%", "")));
		try {
			number = format.parse(saleDealDto.getPlacementFee());
			deal.setPlacementFee(new BigDecimal(number.doubleValue()));
		} catch (ParseException e) {
			System.out.println("Error in parsing Placement Fee:" + saleDealDto.getPlacementFee());
			saleDealDto.setSuccess(false);
			saleDealDto.setStatus("Invalid Placement fee!");
			return deal;
		}
		if (saleDealDto.getSecMarket() == 1) {
			deal.setSecondaryMarket((byte) 1);
			deal.setSellerName(saleDealDto.getSecBuyerName());
			deal.setBankAccount(saleDealDto.getSecBuyerBankAc());
		} else {
			deal.setSecondaryMarket((byte) 0);
		}
		return deal;
	}

	public SaleDealDto mapDealToDto(Deal deal) {
		DealDao dealDao = new DealDao();
		NumberFormat nf = new DecimalFormat("###,##0.0000");
		NumberFormat ratenf = new DecimalFormat("###,##0.00");
		DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
		SaleDealDto saleDealDto = new SaleDealDto();
		saleDealDto.setId(deal.getId());
		saleDealDto.setDealCode(deal.getDealCode());
		saleDealDto.setFund(deal.getFund().getId());
		saleDealDto.setValueDate(df.format(deal.getValueDate()));
		SaledealMapping mapping = dealDao.getSaleMappingByDealId(deal.getId());
		saleDealDto.setInstrumentType(mapping.getInstrumentBean().getInstrumentType().getId());
		saleDealDto.setInsId(mapping.getInstrumentBean().getId());
		saleDealDto.setInstrumentCode(mapping.getInstrumentBean().getInstrumentCode());
		saleDealDto.setPurchDeal(mapping.getPurcahseDeal().getId());
		saleDealDto.setBuyer(deal.getIssuer().getId());
		saleDealDto.setSecMarket(deal.getSecondaryMarket());
		if (saleDealDto.getSecMarket() == 1) {
			saleDealDto.setSecBuyerName(deal.getSellerName());
			saleDealDto.setSecBuyerBankAc(deal.getSellerName());
		}
		saleDealDto.setSellingValue(nf.format(deal.getDealValue().doubleValue()));
		if (deal.getActualRate() != null)
			saleDealDto.setSellingRate(ratenf.format(deal.getActualRate().doubleValue()) + "%");
		saleDealDto.setSellingAmount(nf.format(deal.getMaturityValue()));
		saleDealDto.setPlacementFee(nf.format(deal.getPlacementFee().doubleValue()));
		saleDealDto.setUser(deal.getCreatedUser());
		saleDealDto.setStatus(deal.getStatus());
		if (deal.getSettlementMethod() != null) {
			saleDealDto.setSettlementCode(deal.getSettlementMethod().getId());
		}
		if (deal.getDelevarymethode() != null) {
			saleDealDto.setDelevarymethode(deal.getDelevarymethode().getId());
		}
		if (deal.getDealerCode() != null) {
			saleDealDto.setDealerCode(deal.getDealerCode().getId());
		}
		return saleDealDto;
	}

	public SaleDealDto evaluateSaleDealValue(SaleDealDto saleDealDto, InstrumentType insType) {

		DealDao dealDao = new DealDao();
		InstrumentDao instrumentDao = new InstrumentDao();
		PurchaseCalculator purchase = new PurchaseCalculator();
		Deal purchDeal = dealDao.getById(saleDealDto.getPurchDeal());
		Instrument instrument = instrumentDao.getById(saleDealDto.getInsId());

		String wht = null;
		if (purchDeal.getWithholdingTax() != null) {
			wht = purchDeal.getWithholdingTax();
		} else {
			wht = insType.getWithholdingTax().toString();
		}

		double maturityvalue;
		double rate = Double.parseDouble(saleDealDto.getSellingRate().replace("%", ""));
		double couponRate = instrument.getCouponRate() != null ? instrument.getCouponRate().doubleValue() : 0;
		double whtRate = 0;
		Date purchaseDate = null;
		Date maturityDate = null;
		int dayCount;

		Number number;
		NumberFormat format = NumberFormat.getInstance();
		DateFormat df = new SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH);
		NumberFormat nf = new DecimalFormat("###,##0.0000");

		try {
			number = format.parse(saleDealDto.getSellingAmount());
			maturityvalue = number.doubleValue();
		} catch (ParseException pe) {
			System.out.println("DealValue parse Error: " + saleDealDto.getSellingAmount());
			maturityvalue = 0;
			saleDealDto.setSuccess(false);
			saleDealDto.setStatus("DealValue parse Error: " + saleDealDto.getSellingAmount());
		}
		number = null;
		try {
			purchaseDate = df.parse(saleDealDto.getValueDate());
		} catch (ParseException pe) {
			System.out.println("Value Date parse error: " + saleDealDto.getValueDate());
			purchaseDate = new Date();
			saleDealDto.setSuccess(false);
			saleDealDto.setStatus("Value Date parse error: " + saleDealDto.getValueDate());
		}

		maturityDate = purchDeal.getMaturityDate();

		if (purchDeal.getDayBasis().equals("Act / 360")) {
			dayCount = 360;
		} else if (purchDeal.getDayBasis().equals("Act / 364")) {
			dayCount = 364;
		} else if (purchDeal.getDayBasis().equals("30 / 360")) {
			dayCount = 360;
		} else {
			dayCount = 365;
		}

		if (wht.equals("Upfront") || wht.equals("Maturity")) {
			whtRate = purchDeal.getWithholdingTaxRate().doubleValue();
		}

		if (!saleDealDto.isSuccess()) {
			System.out.println("PurchaseCalculator Evaluation Failed : " + saleDealDto.getStatus());
		} else if (insType.getInterestRate() == InterestRate.F && insType.getInterestType() == InterestType.S && insType.getCouponAvailability() == 0 && wht.equals("No")) {
			System.out.println("FSNN" + maturityvalue + ":" + rate + ":" + purchaseDate + ":" + maturityDate + ":" + dayCount);
			purchase.valuateCpaDealValueFsnn(maturityvalue, rate, purchaseDate, maturityDate, dayCount);
			saleDealDto.setSellingValue(nf.format(purchase.getPrvalBeforeWhtd()));
		} else if (insType.getInterestRate() == InterestRate.F && insType.getInterestType() == InterestType.S && insType.getCouponAvailability() == 0 && wht.equals("Upfront")) {

		} else if (insType.getInterestRate() == InterestRate.F && insType.getInterestType() == InterestType.S && insType.getCouponAvailability() == 0 && wht.equals("Maturity")) {

		} else if (insType.getInterestRate() == InterestRate.F && insType.getInterestType() == InterestType.S && insType.getCouponAvailability() == 1 && wht.equals("No")) {

		} else if (insType.getInterestRate() == InterestRate.F && insType.getInterestType() == InterestType.S && insType.getCouponAvailability() == 2 && wht.equals("No")) {

		} else {

		}
		return saleDealDto;
	}

}
